/******************************************************************************
** 公司名称：天津柯迪斯科技有限公司
** 版权信息：
** 文件名称： App_Protocol_J.c
** 模块名称： J协议处理模块
** 版 本 号： V1.0
** 作    者： 蒲磊
**
** 修改记录： 版本     修改人      时间         修改内容
******************************************************************************/

/******************************************************************************
* 头文件
******************************************************************************/
#include <string.h>
#include "Config.h"
#include "App_Protocol.h"
#include "App_MainTask.h"
#include "App_Parameter.h"
/******************************************************************************
* 本文件宏定义 ('#define')
******************************************************************************/
#define FRAME_LEN_MAX		50		/*最大帧长度*/
#define LOOP_CYCLE          25      /*Loop函数轮询周期，单位ms*/
/******************************************************************************
* 本文件类型定义 ('typedef')
******************************************************************************/

/******************************************************************************
* 本文件静态函数声明 ('static')
******************************************************************************/
static void vPROTOCOL_Factory_Command(void);
extern WM_HWIN DisplayMessage(const char * Text);

static void vPROTOCOL_Get_Data_J(void);
static void vPROTOCOL_Send_J(void);



/******************************************************************************
* 全局变量定义
******************************************************************************/
uint8_t gucRx_Buffer[FRAME_LEN_MAX] = {0};
uint8_t gucTx_Buffer[FRAME_LEN_MAX] = {0};
uint8_t 					gucRx_Frame_OK 	= 0;
uint16_t 					gusRx_Len 		= 0;
stRECEIVED_DATA			gtReceived_Data 	= {0};
stSEND_DATA				gtSend_Data			= {0};
enSEND_DATA_TYPE		geSend_Data_Type 	= Send_Stop;
uint8_t					gucTimeOutError 	= 0;
uint32_t                gulCommunicationCnt = 0;

uint8_t                 gucReceivedConfigFrame = 0;/*是否已接收到配置帧标记*/
uint8_t                 gucRequestSendConfigData = 0;/*请求发送配置帧标记*/
uint8_t                 gucStartReceive = 0;		/*是否开始接收标志*/
uint8_t                 gucReceiveCnt = 0;			/*接收计数*/
/*****************************************************************************
* 函数实现 - global ('extern') and local ('static')
******************************************************************************/


/******************************************************************************
** 功  能：获取一帧协议数据
** 参  数：pData-指向数据的指针，Len-数据长度
** 返回值：无
** 备  注：该函数是协议处理模块对外获取数据的接口，接收到完整一帧后，调用该函数进行处理
******************************************************************************/
void vPROTOCOL_Get_OneFrame(uint8_t *pData,uint16_t Len)
{
    if(Len > 1)		/*如果接收到的数据大于1字节，认为是一个完整帧（DMA+IDLE中断接收），直接放入缓存进行处理*/
    {
        memcpy(gucRx_Buffer,pData,Len);		/*将数据拷贝到缓冲区*/
        gusRx_Len = Len;					/*数据长度*/
        gucRx_Frame_OK = 1;					/*接收到一帧标志置1*/
        gucStartReceive = 0;
    }
    else	/*如果只接收到1个字节，认为控制器是按照单个字节发送，则利用帧间超时来判断一帧接收完毕*/
    {
        if(gucStartReceive == 0)
        {
            gucStartReceive = 1;		/*标记开始接收*/
            gucReceiveCnt = 0;
        }
        gucRx_Buffer[gucReceiveCnt] = *pData;
        if(++gucReceiveCnt > FRAME_LEN_MAX)
        {
            gucReceiveCnt = 0;
            gucStartReceive = 0;
        }
    }
}

/******************************************************************************
** 功  能：解析协议数据
** 参  数：无
** 返回值：无
** 备  注：该函数在主函数中被循环调用。用于解析接收到的协议数据
******************************************************************************/
void vPROTOCOL_Loop(void)
{
    static uint16_t lusCnt = 0;

    static uint8_t  lucReadBatCnt = 0;
    static uint8_t  lucReceiveCnt = 0;	/*用于保存上一次的接收计数*/

    if(gucStartReceive == 1)
    {
        if((gucReceiveCnt > 0) && (gucReceiveCnt == lucReceiveCnt))
        {
            gucStartReceive = 0;
            gusRx_Len = gucReceiveCnt;
            gucRx_Frame_OK = 1;
            gucReceiveCnt = 0;
        }
        else
        {
            lucReceiveCnt = gucReceiveCnt;
        }
    }
    else
    {
    }

    if(gucRx_Frame_OK == 1)
    {
        gulCommunicationCnt = ulBsp_Getticks();
        gucTimeOutError = 0;
        if(gucRx_Buffer[0] == 0x3A && gucRx_Buffer[1] == 0x1C)
        {
            /*内部控制指令*/
            vPROTOCOL_Factory_Command();
        }
        else
        {
            /*调用不同的协议进行解析*/
            vPROTOCOL_Get_Data_J();

        }
        gucRx_Frame_OK = 0;
    }
    else
    {
        /*通讯超时时间，10s*/
        if(ulBsp_Getticks() - gulCommunicationCnt > 10000)
        {
            gucTimeOutError = 1;
            gtReceived_Data.Speed_Cnt = 0;  /*确保返回速度为0*/
        }
//        /*当发送状态为停止时，不报通讯超时错误*/
//        if(geSend_Data_Type != Send_Stop)
//        {
//            /*通讯超时时间，10s*/
//            if(ulBsp_Getticks() - gulCommunicationCnt > 10000)
//            {
//                gucTimeOutError = 1;
//                gtReceived_Data.Speed_Cnt = 0;  /*确保返回速度为0*/
//            }
//        }
//        else
//        {
//            gucTimeOutError = 0;
//            gulCommunicationCnt = ulBsp_Getticks();
//        }
    }
    /*500ms发送一次数据。根据Loop函数的调用周期，计算次数*/
    if(++lusCnt > (500 / LOOP_CYCLE) - 1)
    {
        lusCnt = 0;
        vPROTOCOL_Send_J();
    }
}

/******************************************************************************
** 功  能：设置大灯状态
** 参  数：State-大灯状态。0-关闭，1-打开
** 返回值：无
** 备  注：所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Lamp(uint8_t State)
{
    gtSend_Data.Lamp = State == 0 ? 0 : 1;
}



/******************************************************************************
** 功  能：设置档位
** 参  数：Pas-档位值，最大为9，最小为-1,-1表示助推档
** 返回值：无
** 备  注：本函数不对档位值的合理性做检查。请保证传入的档位值正确。
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Pas(int8_t Pas)
{
    if(Pas > -1)
    {
        gtSend_Data.Pas = Pas;
        gtSend_Data.Push = 0;
    }
    else
    {
        gtSend_Data.Push = 1;
    }
}

/******************************************************************************
** 功  能：设置限速值
** 参  数：Speed-限速值
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Set_Speed_Limit(uint16_t Speed)
{
    gtSend_Data.Speed_Limit = Speed;
}

/******************************************************************************
** 功  能：设置轮径
** 参  数：Wheel-轮径值
** 返回值：无
** 备  注：为了和其它协议兼容，传入的轮径值是实际值的10倍
******************************************************************************/
void vPROTOCOL_Set_Wheel(uint16_t Wheel)
{
    gtSend_Data.Wheel_Diameter = Wheel / 10;
}

/******************************************************************************
** 功  能：设置欠压标志
** 参  数：Battery_Low-欠压标志，0-不欠压，1-欠压
** 返回值：无
** 备  注：本函数不对传入值的合理性做检查。请保证传入的值正确。
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Battery_Low(uint8_t Battery_Low)
{
    gtSend_Data.Battery_Low = Battery_Low == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置助推时的最大PWM
** 参  数：PWM-最大PWM值，0-255
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_PWM(uint8_t PWM)
{
    gtSend_Data.Max_PWM = PWM;
}

/******************************************************************************
** 功  能：设置助力方向
** 参  数：Assistant_Dir-助力方向，0-正向，1-反向
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Assistant_Dir(uint8_t Assistant_Dir)
{
    gtSend_Data.Assistant_Dir = Assistant_Dir == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置助力磁钢数
** 参  数：Assistant_Num-助力磁钢数
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Assistant_Num(uint8_t Assistant_Num)
{
    gtSend_Data.Assistant_Num = Assistant_Num;
}

/******************************************************************************
** 功  能：设置助力灵敏度（助力过几个磁钢开始）
** 参  数：Assistant_Sensitivity-助力灵敏度
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Assistant_Sensitivity(uint8_t Assistant_Sensitivity)
{
    if(Assistant_Sensitivity > 63)
    {
        Assistant_Sensitivity = 63;     /*设置最大值*/
    }
    if(Assistant_Sensitivity == 0)
    {
        Assistant_Sensitivity = 1;      /*助力灵敏度不能为0*/
    }
    gtSend_Data.Assistant_Sensitivity = Assistant_Sensitivity;
}

/******************************************************************************
** 功  能：设置速度传感器数量
** 参  数：Speed_Sensor_Num-速度传感器数量
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Speed_Sensor_Num(uint8_t Speed_Sensor_Num)
{
    if(Speed_Sensor_Num > 15)
    {
        Speed_Sensor_Num = 15;
    }
    gtSend_Data.Speed_Sensor_Num = Speed_Sensor_Num;
}

/******************************************************************************
** 功  能：设置启动强度（缓启动参数）
** 参  数：Start_Strength-启动强度
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Start_Strength(uint8_t Start_Strength)
{
    if(Start_Strength > 3)
    {
        Start_Strength = 3;
    }
    gtSend_Data.Start_Strength = Start_Strength;
}

/******************************************************************************
** 功  能：设置转把是否支持助推
** 参  数：Handle_Push-转把是否支持助推，0-正常转把，1-转把6km助推
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Handle_Push(uint8_t Handle_Push)
{
    gtSend_Data.Handle_Push = Handle_Push == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置转把是否支持分档
** 参  数：Handle_Segement-转把是否支持分档，0-转把不分档，1-转把分档
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Handle_Segement(uint8_t Handle_Segement)
{
    gtSend_Data.Handle_Segement = Handle_Segement == 0 ? 0 : 1;
}

/******************************************************************************
** 功  能：设置系统欠压值
** 参  数：Low_Voltage-系统欠压值，分辨率：0.1V
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Low_Voltage(uint16_t Low_Voltage)
{
    gtSend_Data.Low_Voltage = Low_Voltage;
}

/******************************************************************************
** 功  能：设置系统电压值
** 参  数：Sys_Voltage-系统电压值，分辨率：1V，支持：24V，36V，48V
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Sys_Voltage(uint16_t Sys_Voltage)
{
    gtSend_Data.Sys_Voltage = Sys_Voltage;
}

/******************************************************************************
** 功  能：设置系统限流值
** 参  数：Current_Limit-系统限流值，分辨率：0.5V
** 返回值：无
** 备  注：
** 适用协议：5S
******************************************************************************/
void vPROTOCOL_Set_Current_Limit(uint16_t Current_Limit)
{
    gtSend_Data.Current_Limit = Current_Limit;
}

/******************************************************************************
** 功  能：设置档位范围
** 参  数：Pas_Range-档位值范围，3，4，5，9
** 返回值：无
** 备  注：J协议不支持档位范围设置，为了兼容其他协议，该函数为空即可。
******************************************************************************/
void vPROTOCOL_Set_Pas_Range(int8_t Pas_Range)
{

}

/******************************************************************************
** 功  能：设置发送运行数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即开始发送运行数据。直到再次设置发送配置数据或停止
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Run_Data(void)
{
    geSend_Data_Type = Send_Run_Data;
}

/******************************************************************************
** 功  能：设置发送配置数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即开始发送配置数据。直到再次设置发送运行数据或停止
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Config_Data(void)
{
    geSend_Data_Type = Send_Run_Data;/*按照J协议，在配置时应该发送配置帧，但是之前的程序都发送的运行帧，切模拟软件也不响应配置帧，因此此处也发送运行帧*/
}

/******************************************************************************
** 功  能：设置发送一次配置数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，只发送一次配置数据。然后会转为发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Config_Data_OneTime(void)
{
    geSend_Data_Type = Send_Config_Data_OneTime;
}

/******************************************************************************
** 功  能：停止发送数据
** 参  数：无
** 返回值：无
** 备  注：本函数运行后，即停止发送数据。直到再次设置发送配置数据或发送运行数据
**         所有协议通用
******************************************************************************/
void vPROTOCOL_Send_Stop(void)
{
    geSend_Data_Type = Send_Stop;
}

/******************************************************************************
** 功  能：获取电量等级
** 参  数：无
** 返回值：电量等级。0-表示欠压，1-5表示电量等级
** 备  注：J协议用
******************************************************************************/
uint8_t ucPROTOCOL_Get_Volt_Level(void)
{
    return gtReceived_Data.Volt_Level;
}

/******************************************************************************
** 功  能：获取当前电流值
** 参  数：无
** 返回值：实际电流值的10倍。比如实际电流12.3A，返回123
** 备  注：所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Current(void)
{
    if(gucTimeOutError == 1)
    {
        return 0;
    }
    else
    {
        return gtReceived_Data.Current;
    }
}

/******************************************************************************
** 功  能：获取电池容量
** 参  数：无
** 返回值：-1表示未获取到电池容量，电池容量，0-100%
** 备  注：J协议不支持SOC，返回-1，为了兼容其他协议。
******************************************************************************/
int8_t cPROTOCOL_Get_Soc(void)
{
    return -1;
}

/******************************************************************************
** 功  能：获取当前车轮转动一周的计数
** 参  数：无
** 返回值：车轮转一周的计数
** 备  注：本函数不对数值的正确性做检查
**         所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed_Cnt(void)
{
    return gtReceived_Data.Speed_Cnt;
}

/******************************************************************************
** 功  能：获取当前车速
** 参  数：无
** 返回值：实际车速*10.比如返回120，实际车速即12.0Km/h
** 备  注：所有协议通用
******************************************************************************/
uint16_t usPROTOCOL_Get_Speed(void)
{
    if(gtReceived_Data.Speed_Cnt >= 0x0DAC || gtReceived_Data.Speed_Cnt == 0 || gucTimeOutError == 1)
    {
        /*如果车轮转动一周的时间大于等于3500，或者等于0，或者通讯超时，即认为速度为0*/
        return 0;
    }
    else
    {
        if(gtSend_Data.Wheel_Diameter == 27 && ((CONFIG_27INCH_DISPLAY == DISPLAY_700C) || (CONFIG_27INCH_DISPLAY == DISPLAY_275)))
        {
            /*轮径27，按照27.5Inch计算，周长698.5mm，698.5*314*36/100=78958*/
            return 78958 / gtReceived_Data.Speed_Cnt;
        }
        else if(gtSend_Data.Wheel_Diameter == KDS_WHEEL_SPECIAL) //特殊定制
        {
            return 2200 * 36 / gtReceived_Data.Speed_Cnt;
        }
        else
        {
            /*其它轮径，按照英寸计算，1inch=25.4mm，25.4*314*36/100=2871*/
            return 2871 * gtSend_Data.Wheel_Diameter / gtReceived_Data.Speed_Cnt;
        }
    }
}

/******************************************************************************
** 功  能：获取错误代码
** 参  数：无
** 返回值：十六进制的错误代码
** 备  注：包括30错误代码（通信超时）
**         所有协议通用
******************************************************************************/
uint8_t ucPROTOCOL_Get_Errcode(void)
{
    if(gucTimeOutError == 1)
    {
        return 0x30;
    }
    else
    {
        return gtReceived_Data.ErrCode;
    }
}

/******************************************************************************
** 功  能：工厂指令的应答
** 参  数：Cmd-要应答的指令，Response-要应答的参数
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Factory_Response(uint8_t Cmd,uint16_t Response)
{
    uint8_t lucRxBuffer[8];


    lucRxBuffer[0] = 0x3A;  /*0x3A,0x50是应答帧的帧头*/
    lucRxBuffer[1] = 0x50;
    lucRxBuffer[2] = Cmd;
    lucRxBuffer[3] = Response & 0x00FF;
    lucRxBuffer[4] = (Response >> 8) & 0x00FF;
    lucRxBuffer[5] = lucRxBuffer[2] + lucRxBuffer[3] + lucRxBuffer[4]; /*8位的和校验*/
    lucRxBuffer[6] = 0x0D;
    lucRxBuffer[7] = 0x0A;  /*0x0D,0x0A是固定帧尾*/

    USART_MCU_Send_Frame(lucRxBuffer,8);

}


/******************************************************************************
** 功  能：工厂指令的解析
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Factory_Command(void)
{
    uint16_t n;
    uint16_t lusCheckSum = 0;
    uint16_t lusResponse;

    for(n = 0; n < gusRx_Len - 5; n++)
    {
        lusCheckSum += gucRx_Buffer[1 + n];		/*计算校验值，和校验*/
    }
    if((gucRx_Buffer[3] == gusRx_Len - 8) && (lusCheckSum == gucRx_Buffer[gucRx_Buffer[3] + 5] * 256UL + gucRx_Buffer[gucRx_Buffer[3] + 4]))
    {
        switch(gucRx_Buffer[2])
        {
        case 0x5D:		/*电压校准*/
        {
            lusResponse = vVoltage_Calibration();
            vPROTOCOL_Factory_Response(0x5D,lusResponse);
            break;
        }
        case 0x8E:		/*清除ODO*/
        {
            vClear_ODO();
            vPROTOCOL_Factory_Response(0x8E,5678); /*5678是针对清ODO的固定响应*/
            break;
        }
        case 0x6E:		/*校准光感*/
        {
            lusResponse = vPhotoDiode_Calibration();
            vPROTOCOL_Factory_Response(0x6E,lusResponse);
            break;
        }
        case 0x71:		/*自动校准时间*/
        {
            vDateTime_Calibration(gucRx_Buffer[7],gucRx_Buffer[8],gucRx_Buffer[9],gucRx_Buffer[4],gucRx_Buffer[5],gucRx_Buffer[6]);
            vPROTOCOL_Factory_Response(0x71,1234); /*1234是针对校准时间的固定响应*/
            break;
        }
        default:
            break;
        }
    }
}


/******************************************************************************
** 功  能：解析J协议数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Get_Data_J(void)
{
    uint8_t Checksum = 0;
    uint8_t n;
    for(n = 0; n < 6; n++)
    {
        Checksum ^= gucRx_Buffer[n + 1];	/*计算校验值*/
    }
    /*首字节是F，并且校验正确，认为接收数据无误*/
    if(gucRx_Buffer[0] == 'F' && gucRx_Buffer[gusRx_Len - 1] == Checksum)
    {
        gtReceived_Data.Volt_Level	= gucRx_Buffer[1];					/*电量值*/
        gtReceived_Data.Current		= gucRx_Buffer[2] * 10 / 3;			/*实际电流值 = 接收到的值 / 3.扩大10倍输出*/
        gtReceived_Data.Speed_Cnt	= (uint16_t)gucRx_Buffer[3] << 8 | gucRx_Buffer[4];		/*车轮转动一周的脉冲时间*/
        if(gucRx_Buffer[6] == 0x21 || gucRx_Buffer[6] == 0x22 || gucRx_Buffer[6] == 0x23 | gucRx_Buffer[6] == 0x24 || gucRx_Buffer[6] == 0x25)
        {
            gtReceived_Data.ErrCode	= gucRx_Buffer[6];					/*错误代码*/
        }
        else
        {
            gtReceived_Data.ErrCode = 0x00;			/*错误代码如果是其它值，都认为是无错误*/
        }
    }

    return;
}

/******************************************************************************
** 功  能：发送J协议数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
static void vPROTOCOL_Send_J(void)
{
    uint8_t lucWheel_Index;
    uint8_t lucSpeed_Limit;
    uint8_t lucChecksum;
    static uint8_t lucOverSpeed = 0;/*超速移植*/

    switch(geSend_Data_Type)
    {
    case Send_Stop:
    {
        return;						/*停止发送，直接退出*/
    }
    case Send_Run_Data:
    {
        gucTx_Buffer[0] = 'F';		/*正常工作数据，帧头标志是F*/
        break;
    }
    case Send_Config_Data:
    case Send_Config_Data_OneTime:
    {
        gucTx_Buffer[0] = 'S';		/*设置数据，帧头标志是S*/
        break;
    }

    }
    /*大灯状态，档位，推行模式*/
    if((usPROTOCOL_Get_Speed() > gtSend_Data.Speed_Limit * 10) && ((NO_LIMIT_WHEN_MAX == 0) || ((NO_LIMIT_WHEN_MAX == 1) && (gtSend_Data.Speed_Limit != CONFIG_SPEED_MAX))))
    {
        lucOverSpeed = 1;/*超速标志置位*/
        gucTx_Buffer[1] = (0x00 | (gtSend_Data.Lamp << 7) | (gtSend_Data.Push << 4) | 0x00);				/*超速时发0档*/
    }
    else
    {
        /*当车速降低到限速值-1时，清超速标志位*/
        if(usPROTOCOL_Get_Speed() < (gtSend_Data.Speed_Limit - 1) * 10)
        {
            lucOverSpeed = 0;
        }

        if(lucOverSpeed == 1)
        {
            gucTx_Buffer[1] = (0x00 | (gtSend_Data.Lamp << 7) | (gtSend_Data.Push << 4) | 0x00);				/*超速时发0档*/
        }
        else
        {
            if(gtSend_Data.Push == 1)
            {
                gucTx_Buffer[1] = (0x00 | (gtSend_Data.Lamp << 7) | (gtSend_Data.Push << 4) | 0x00);	/*助推时要求发0 2022.06.30规定*/
            }
            else
            {
                gucTx_Buffer[1] = (0x00 | (gtSend_Data.Lamp << 7) | (gtSend_Data.Push << 4) | (gtSend_Data.Pas == 0?0x0F:gtSend_Data.Pas));	/*0档发0x0F，其它档位按实际发*/
            }
        }
    }

    if(gtSend_Data.Wheel_Diameter < 16)
    {
        lucWheel_Index = 0;		/*轮径小于16时，发0*/
    }
    else if(gtSend_Data.Wheel_Diameter < 27)
    {
        lucWheel_Index = (gtSend_Data.Wheel_Diameter - 16) / 2;	/*16-26寸之间的轮径，依次为0，1，2，3，4，5，中间值向下靠拢*/
    }
    else if(gtSend_Data.Wheel_Diameter == 27)
    {
        lucWheel_Index = 6;			/*27.5或者700C的轮径，发送6*/
    }
    else
    {
        lucWheel_Index = 7;			/*大于等于28的轮径，发送7*/
    }
    if(gtSend_Data.Speed_Limit < LIMIT_SPEED_OFFECT)
    {
        gtSend_Data.Speed_Limit = LIMIT_SPEED_OFFECT;
    }
    lucSpeed_Limit = gtSend_Data.Speed_Limit - LIMIT_SPEED_OFFECT;
    if(lucSpeed_Limit > 31)
    {
        lucSpeed_Limit = 31;		/*J协议的限速值，最大只能发送31，即限速41km/h*/
    }
    gucTx_Buffer[2] = (lucSpeed_Limit << 3) | lucWheel_Index;
    gucTx_Buffer[3] = 0x00;			/*校验调整值先设为0*/
    lucChecksum = gucTx_Buffer[1] ^ gucTx_Buffer[2] ^ gucTx_Buffer[3];
    /*如果校验值正好等于0x0D，则校验调整值增加，并重新校验，直到不等于0x0D*/
    while(lucChecksum == 0x0D)
    {
        gucTx_Buffer[3]++;
        lucChecksum = gucTx_Buffer[1] ^ gucTx_Buffer[2] ^ gucTx_Buffer[3];
    }
    gucTx_Buffer[4] = lucChecksum;
    gucTx_Buffer[5] = 0x0D;					/*帧尾，固定为0x0D*/

    USART_MCU_Send_Frame(gucTx_Buffer,6);		/*发送数据*/
    /*如果状态标记为只发送一次配置数据，那么发送完毕后，将状态标记为发送运行数据*/
    if(geSend_Data_Type == Send_Config_Data_OneTime)
    {
        geSend_Data_Type = Send_Run_Data;
    }
}

/******************************************************************************
** 功  能：复位通信超时计数变量
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_ResetCommunicationOverTime(void)
{
    __disable_irq();
    gucTimeOutError = 0;
    gulCommunicationCnt = ulBsp_Getticks();
    __enable_irq();

}


/******************************************************************************
** 功  能：开机上电时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_PowerOn(void)
{
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));
    vPROTOCOL_Set_Pas_Range(gtParam.Pas_Max);
    vPROTOCOL_Set_Pas(0);/*开机LOGO界面发0档*/
    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit);
    vPROTOCOL_Send_Run_Data();
}

/******************************************************************************
** 功  能：退出设置时，设置默认要发送给控制器的数据
** 参  数：无
** 返回值：无
** 备  注：
******************************************************************************/
void vPROTOCOL_Set_Value_When_ExitSetting(void)
{
    vPROTOCOL_Set_Wheel(usGet_Wheel_Size(gtParam.Wheel_Diameter));
    vPROTOCOL_Set_Speed_Limit(gtParam.Speed_Limit);
    vPROTOCOL_Send_Config_Data_OneTime();
}

